package org.example;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.comments.Comment;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


@Mojo(name = "sql",defaultPhase = LifecyclePhase.COMPILE)
public class MyMojo   extends AbstractMojo
{
    /**
     * maven仓库目录
     */
    @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
    protected ArtifactRepository localRepository;
    /**
     * 项目根目录
     */
    @Parameter(defaultValue = "${basedir}")
    private File baseDir;
    /**
     * 资源目录
     */
    @Parameter(defaultValue = "${project.build.resources}",readonly = true,required = true)
    private List<Resource> resources;
    /**
     * 源码目录
     */
    @Parameter(defaultValue = "${project.build.sourceDirectory}",required = true,readonly = true)
    private File sourceDir;
    /**
     * 测试资源
     */
    @Parameter(defaultValue = "${project.build.testResources}",readonly = true,required = true)
    private List<Resource> testResources;
    /**
     * 测试代码目录
     */
    @Parameter(defaultValue = "${project.build.testSourceDirectory}",readonly = true,required = true)
    private File testSourceDir;

    @Parameter(property ="count.include")
    private String[] includes;

    @Parameter(property="scanPackage")
    private List<String> scanPackage;

    @Parameter(property="mapperPath")
    private String mapperPath;
    /**
     *
     *
     */
    public void execute()  throws MojoExecutionException
    {
        Optional<File> sourceDir = Optional.ofNullable(this.sourceDir);
        if (sourceDir.isPresent()) {
            //根目录
            Path path = sourceDir.get().toPath();

            for (String s : scanPackage) {
                String replace = s.replace(".", "/");
                Path normalize = path.resolve(replace).normalize();
                try {
                    List<Path> collect = Files.walk(normalize).filter(x -> x.toString().endsWith(".java")).collect(Collectors.toList());
                    for (Path pt : collect) {

                        JavaParser parser = new JavaParser();
                        CompilationUnit compilationUnit = parser.parse(pt).getResult().get();
                        //找出所有类
                        NodeList<TypeDeclaration<?>> types = compilationUnit.getTypes();

                        for (TypeDeclaration<?> type : types) {
                            //全类名
                            String clsName = type.getFullyQualifiedName().get();

                            StringBuffer sf = new StringBuffer();
                            sf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                            sf.append("\n<mapper nameSpaces=\""+clsName+"\">");
                            List<MethodDeclaration> methods = type.getMethods();
                            List<MethodDeclaration> lst = methods.stream().filter(x ->Optional.ofNullable(x.getComment()).isPresent()).collect(Collectors.toList());
                            for (MethodDeclaration methodDeclaration : lst) {
                                Optional<Comment> comment = methodDeclaration.getComment();
                                if (comment.isPresent()) {
                                    //方法名
                                    String method  = methodDeclaration.getNameAsString();
                                    //内容
                                    String content = comment.get().getContent();
                                    String subSql = subSql(content);
                                    sf.append("\n");
                                    sf.append(subSql);
                                    sf.append("\n");
                                }
                            }
                            sf.append("</mapper>");
                            String directory = resources.get(0).getDirectory();

                            File file1 = new  File(directory+"/"+mapperPath+"/"+type.getNameAsString()+".xml");
                            if (!file1.exists() || !file1.isFile() ){
                                file1.createNewFile();
                            }
                            FileOutputStream file = new FileOutputStream(file1);
                            file.write(sf.toString().getBytes());
                            file.flush();
                            file.close();
                        }

                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }


    }


    private String subSql(String content){

        int start = indexOf(content, "<code>");

        int end = indexOf(content, "</code>");

        if (start >=5 && end> 12 && start < end) {
            return content.substring(start +1, end -6).replaceAll("[*|\r|\n|\t]","");
        }

        throw new RuntimeException("获取SQL解析失败");
    }

    /**
     *
     * @param cont  用于查找的字符串
     * @param search    要查找的字符串
     * @return  索引位置
     */
    private int indexOf(String cont ,String search){

        Optional<String> con = Optional.ofNullable(cont);

        if(con.isPresent()){
            String s = con.get();

            char[] chars = s.toCharArray();
            char[] chs = search.toCharArray();
            StringBuffer sf = new StringBuffer();

            for (int i = 0; i < chars.length; i++) {
                char aChar = chars[i];
                int index = charArrayIndexOf(chs,aChar);

                if ( index > -1 ) {
                    if (sf.length() == index) {
                        sf.append(aChar);
                    }else{
                        sf.setLength(0);
                    }
                }else if (aChar != ' '){
                    //如果是非空字符 且不是要查找的字符
                    sf.setLength(0);
                }else{
                    //如果是空 跳出检查 进入下一个字符检查
                  continue;
                }

                if(sf.toString().equalsIgnoreCase(search)){
                   return i;
                }
            }
        }

        return -1;
    }

    /**
     *  查找字符在字符数组中的索引位置
     * @param chs 用于查找的字符数组
     * @param aChar 要查找的字符
     * @return  位置
     */
    private int charArrayIndexOf(char[] chs, char aChar) {
        for (int i = 0; i < chs.length; i++) {
            if (chs[i] == aChar){
                return i;
            }
        }
        return -1;
    }
}
